/*
 * The contents of this file are subject to the Mozilla Public License
 * Version 1.1 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
 * License for the specific language governing rights and limitations
 * under the License.
 * 
 * The Original Code is iSQL-Viewer, A Mutli-Platform Database Tool.
 *
 * The Initial Developer of the Original Code is iSQL-Viewer, A Mutli-Platform Database Tool.
 * Portions created by Mark A. Kobold are Copyright (C) 2000-2007. All Rights Reserved.
 *
 * Contributor(s): 
 *  Mark A. Kobold [mkobold <at> isqlviewer <dot> com].
 *  
 * If you didn't download this code from the following link, you should check
 * if you aren't using an obsolete version: http://www.isqlviewer.com
 */
package org.isqlviewer.ui;

import java.awt.Cursor;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLStreamHandler;

import javax.swing.JEditorPane;
import javax.swing.SwingUtilities;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.MouseInputAdapter;
import javax.swing.text.AttributeSet;
import javax.swing.text.DefaultStyledDocument;
import javax.swing.text.Position;

/**
 * Class for mouse input support on the SQL command editor.
 * <p>
 * 
 * @author Mark A. Kobold &lt;mkobold at isqlviewer dot com&gt;
 * @version 1.0
 */
public class SqlCommandMouseAdapter extends MouseInputAdapter {

    /**
     * This is used by viewToModel to avoid allocing a new array each time.
     */
    private Position.Bias[] bias = new Position.Bias[1];

    public void mouseClicked(MouseEvent e) {

        JEditorPane editor = (JEditorPane) e.getSource();
        if (SwingUtilities.isLeftMouseButton(e)) {
            Point pt = new Point(e.getX(), e.getY());
            int pos = editor.viewToModel(pt);
            if (pos >= 0) {
                DefaultStyledDocument document = (DefaultStyledDocument) editor.getDocument();
                AttributeSet as = document.getCharacterElement(pos).getAttributes();
                if (Boolean.TRUE == as.getAttribute("hyperlinked")) {
                    activateLink(pos, editor, e.getX(), e.getY());
                }
            }
        }
    }

    public void mouseMoved(MouseEvent e) {

        JEditorPane editor = (JEditorPane) e.getSource();

        Point pt = new Point(e.getX(), e.getY());
        int pos = editor.getUI().viewToModel(editor, pt, bias);
        if (bias[0] == Position.Bias.Backward && pos > 0) {
            pos--;
        }
        boolean setCursor = false;
        if (pos >= 0) {
            DefaultStyledDocument document = (DefaultStyledDocument) editor.getDocument();
            AttributeSet as = document.getCharacterElement(pos).getAttributes();
            if ((e.getModifiers() & org.isqlviewer.swing.SwingUtilities.MENU_SHORTCUT_MASK) == org.isqlviewer.swing.SwingUtilities.MENU_SHORTCUT_MASK) {
                if (Boolean.TRUE == as.getAttribute("hyperlinked")) {
                    setCursor = true;
                }
            }
        }
        if (setCursor) {
            editor.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
        } else {
            editor.setCursor(Cursor.getPredefinedCursor(Cursor.TEXT_CURSOR));
        }
    }

    private void activateLink(int pos, JEditorPane editor, int x, int y) {

        String text = editor.getText();
        int currentLocation = Math.min(text.length() - 1, pos);
        currentLocation = Math.max(0, currentLocation);

        int fromIndex = 0;
        int toIndex = text.length() - 1;
        for (int i = currentLocation; i >= 0; i--) {
            char c = text.charAt(i);
            if (Character.isWhitespace(c)) {
                fromIndex = i;
                break;
            }
        }
        boolean found = false;
        for (int i = currentLocation; i < toIndex; i++) {
            char c = text.charAt(i);
            if (Character.isWhitespace(c)) {
                toIndex = i;
                found = true;
                break;
            }
        }
        if (!found) {
            toIndex = text.length();
        }

        String currentWord = text.substring(fromIndex, toIndex).trim();
        if (currentWord.length() == 0) {
            return;
        }
        URL url;
        try {
            url = new URL("table", null, -1, currentWord, new InternalURLStreamHandler());
            HyperlinkEvent hle = new HyperlinkEvent(editor, HyperlinkEvent.EventType.ACTIVATED, url);
            editor.fireHyperlinkUpdate(hle);
        } catch (MalformedURLException e) {
        }
    }

    private static class InternalURLStreamHandler extends URLStreamHandler {

        @Override
        protected URLConnection openConnection(URL u) throws IOException {

            return new NullURLConnection(u);
        }
    }

    private static class NullURLConnection extends URLConnection {

        protected NullURLConnection(URL url) {

            super(url);
        }

        public void connect() {

        }
    }
}
